---
title: "02-Java 对象的创建与引用"
aliases:
- "Java 对象的创建与引用"
created: 2025-12-24
---
# Java 对象的创建与引用
## **一、使用 new 运算符创建对象**
### **1.1 基本语法**
```
类名 引用变量 = new 类名(构造参数);
// 示例
Student stu = new Student("张三", 20);
```
### **1.2 创建过程分解**
```drawio
```
### **1.3 详细执行步骤**
| **步骤** | **操作** | **说明** |
| --- | --- | --- |
| ① | 加载类 | 如果 Student 类未加载,先加载到方法区 |
| ② | 分配内存 | 在堆中为新对象分配内存空间 |
| ③ | 默认初始化 | 属性赋默认值(0/null/false) |
| ④ | 显式初始化 | 执行属性声明时的赋值 |
| ⑤ | 构造方法 | 执行构造方法中的代码 |
| ⑥ | 返回地址 | 将对象内存地址赋给引用变量 |
### **1.4 代码示例:观察初始化顺序**
```java
public class Student {
// ② 显式初始化
private String name = "默认姓名";
private int age = 0;
// ③ 构造方法
public Student(String name, int age) {
System.out.println("构造前 name = " + this.name); // 输出:默认姓名
this.name = name;
this.age = age;
System.out.println("构造后 name = " + this.name); // 输出:张三
}
public static void main(String[] args) {
Student stu = new Student("张三", 20);
}
}
```
**输出**结果:
```
构造前 name = 默认姓名
构造后 name = 张三
```
## **二、堆内存与栈内存**
### **2.1 JVM 内存结构概览**
```drawio
```
### **2.2 栈内存 vs 堆内存 对比表**
| **特性** | **栈内存 (Stack)** | **堆内存 (Heap)** |
| --- | --- | --- |
| **存储内容** | 局部变量、方法参数、引用地址 | 对象实例、数组 |
| **生命周期** | 方法执行期间 | 直到无引用被 GC 回收 |
| **分配速度** | 快(指针移动) | 慢(需找空闲空间) |
| **空间大小** | 较小(默认 1MB) | 较大(可配置 GB 级) |
| **线程关系** | 线程私有 | 线程共享 |
| **内存管理** | 自动释放 | 垃圾回收器管理 |
| **溢出异常** | StackOverflowError | OutOfMemoryError |
---
### **2.3 代码示例:理解内存分配**
```java
public class MemoryDemo {
public static void main(String[] args) {
// 基本类型 → 值存在栈中
int num = 100;
// 引用类型 → 引用在栈中,对象在堆中
Student stu = new Student("张三", 20);
// 数组也是对象 → 堆中
int[] arr = new int[]{1, 2, 3};
// 调用方法
process(stu);
}
public static void process(Student s) {
// s 是新的引用,指向同一个对象
String name = s.getName(); // name 引用在栈中
}
}
```
**内存图解**:
```drawio
```
## **三、对象实体与对象引用**
### **3.1 核心概念**
```drawio
```
### **3.2 气球与绳子类比**
```drawio
```
### **3.3 代码验证**
```java
public class ReferenceDemo {
public static void main(String[] args) {
// 规则 1:绳子可以不系气球
Student stu1 = null;
// stu1.getName(); // ❌ NullPointerException
// 规则 2:绳子只能系一个气球
Student stu2 = new Student("张三", 20);
System.out.println(stu2.getName()); // 张三
stu2 = new Student("李四", 21); // stu2 改系新气球
System.out.println(stu2.getName()); // 李四
// "张三"对象无人引用,等待 GC 回收
// 规则 3:多条绳子系同一个气球
Student s1 = new Student("王五", 22);
Student s2 = s1; // s2 系上 s1 的气球
Student s3 = s1; // s3 也系上同一个气球
// 验证:修改一处,全部生效
s2.setAge(30);
System.out.println(s1.getAge()); // 30
System.out.println(s3.getAge()); // 30
}
}
```
## **四、引用相等 vs 对象相等**
### **4.1 概念对比**
```drawio
```
### **4.2 代码示例**
```java
public class EqualityDemo {
public static void main(String[] args) {
Student s1 = new Student("张三", 20); // 对象 A
Student s2 = s1; // 也指向对象 A
Student s3 = new Student("张三", 20); // 对象 B(内容相同)
// ====== 引用相等(==):比较地址 ======
System.out.println(s1 == s2); // true (同一对象)
System.out.println(s1 == s3); // false (不同对象)
// ====== 对象相等(equals):比较内容 ======
// 注意:需要 Student 类重写 equals 方法才能正确比较
System.out.println(s1.equals(s3)); // 取决于 equals 实现
}
}
```
**内存示意图**:
```drawio
```
## **五、== 与 equals() 详解**
### **5.1 == 运算符的行为**
| **比较类型** | **== 的作用** | **示例** |
| --- | --- | --- |
| 基本类型 | 比较**值** | `5 == 5` → true |
| 引用类型 | 比较**地址** | `s1 == s2` → 是否同一对象 |
```
// 基本类型用 == 比较值
int a = 100;
int b = 100;
System.out.println(a == b); // true(值相等)
// 引用类型用 == 比较地址
String str1 = new String("Java");
String str2 = new String("Java");
System.out.println(str1 == str2); // false(不同对象)
```
### **5.2 equals() 方法的行为**
#### **Object 类的默认实现(源码)**
```java
// java.lang.Object 类中的 equals 方法
public boolean equals(Object obj) {
return (this == obj); // 默认比较引用!
}
```
> *⚠️ **默认行为与 == 完全相同!** 需要子类重写才能比较内容。*
#### **String 类的重写实现(源码解析)**
```java
// java.lang.String 类中的 equals 方法
public boolean equals(Object anObject) {
// 1️⃣ 先比较引用,相同直接返回 true
if (this == anObject) {
return true;
}
// 2️⃣ 检查类型是否是 String
if (anObject instanceof String) {
String anotherString = (String) anObject;
int n = value.length;
// 3️⃣ 比较长度
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
// 4️⃣ 逐字符比较
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
```
**流程**图:
```drawio
```
### **5.3 自定义类重写 equals()**
```java
public class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object obj) {
// 1. 引用相同
if (this == obj) return true;
// 2. null 检查 + 类型检查
if (obj == null || getClass() != obj.getClass()) return false;
// 3. 强制类型转换
Student student = (Student) obj;
// 4. 比较各属性
return age == student.age &&
Objects.equals(name, student.name);
}
// 重写 equals 必须重写 hashCode(后续笔记详解)
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
```
### **5.4 == vs equals() 对比总结表**
| **比较方式** | **基本类型** | **引用类型(未重写)** | **引用类型(已重写)** |
| --- | --- | --- | --- |
| `==` | 比较值 | 比较地址 | 比较地址 |
| `equals()` | ❌ 不适用 | 比较地址(同==) | 比较内容 |
---
## **六、字符串的特殊情况**
### **6.1 字符串常量池**
```drawio
```
### **6.2 代码验证**
```java
public class StringPoolDemo {
public static void main(String[] args) {
// 字面量创建(使用常量池)
String str1 = "Java";
String str2 = "Java";
// new 创建(强制新对象)
String str3 = new String("Java");
String str4 = new String("Java");
// ====== == 比较(地址)======
System.out.println("str1 == str2: " + (str1 == str2)); // true ✅ 常量池复用
System.out.println("str1 == str3: " + (str1 == str3)); // false ❌ 不同对象
System.out.println("str3 == str4: " + (str3 == str4)); // false ❌ 不同对象
// ====== equals 比较(内容)======
System.out.println("str1.equals(str3): " + str1.equals(str3)); // true ✅
System.out.println("str3.equals(str4): " + str3.equals(str4)); // true ✅
// ====== intern() 方法 ======
String str5 = str3.intern(); // 返回常量池中的引用
System.out.println("str1 == str5: " + (str1 == str5)); // true ✅
}
}
```
**输出结**果:
```
str1 == str2: true
str1 == str3: false
str3 == str4: false
str1.equals(str3): true
str3.equals(str4): true
str1 == str5: true
```
### **6.3 字符串创建方式对比**
| **创建方式** | **代码示例** | **使用常量池** | **内存位置** |
| --- | --- | --- | --- |
| 字面量 | `"Java"` | ✅ 是 | 常量池 |
| new | `new String("Java")` | ❌ 否 | 堆内存 |
| intern() | `str.intern()` | ✅ 是 | 返回常量池引用 |
| 拼接(常量) | `"Ja" + "va"` | ✅ 是 | 编译期优化 |
| 拼接(变量) | `str + "va"` | ❌ 否 | 运行时新建 |
---
## **七、Integer 缓存池**
### **7.1 缓存池机制**
```java
public class IntegerCacheDemo {
public static void main(String[] args) {
// -128 ~ 127 范围内使用缓存
Integer a = 100;
Integer b = 100;
System.out.println(a == b); // true ✅ 使用缓存
// 超出范围,创建新对象
Integer c = 200;
Integer d = 200;
System.out.println(c == d); // false ❌ 不同对象
// equals 比较内容
System.out.println(c.equals(d)); // true ✅
}
}
```
### **7.2 Integer.valueOf() 源码**
```java
// java.lang.Integer 类
public static Integer valueOf(int i) {
// 如果在缓存范围内,返回缓存对象
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
// 否则创建新对象
return new Integer(i);
}
// 缓存池内部类
private static class IntegerCache {
static final int low = -128;
static final int high = 127; // 可通过 JVM 参数调整
static final Integer cache[];
static {
// 初始化缓存数组
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
}
}
```
**流程图**:
```drawio
```
### **7.3 各包装类缓存范围**
| **包装类** | **缓存范围** | **说明** |
| --- | --- | --- |
| Byte | -128 ~ 127 | 全部缓存 |
| Short | -128 ~ 127 | |
| Integer | -128 ~ 127 | high 可通过 JVM 参数调整 |
| Long | -128 ~ 127 | |
| Character | 0 ~ 127 | |
| Boolean | TRUE / FALSE | 只有两个值 |
| Float | ❌ 无缓存 | 浮点数范围太大 |
| Double | ❌ 无缓存 | 浮点数范围太大 |
---
## **八、最佳实践总结**
### **8.1 比较规则速查表**
| **场景** | **推荐方式** | **示例** |
| --- | --- | --- |
| 基本类型比较 | `==` | `int a == int b` |
| 对象内容比较 | `equals()` | `str1.equals(str2)` |
| 对象是否同一个 | `==` | `obj1 == obj2` |
| null 安全比较 | `Objects.equals()` | `Objects.equals(a, b)` |
---
### **8.2 常见陷阱**
```java
// ❌ 陷阱 1:用 == 比较字符串内容
String input = new String("admin");
if (input == "admin") { // false!
// 永远不会执行
}
// ✅ 正确写法
if (input.equals("admin")) {
// 正确执行
}
// ✅ 更安全的写法(避免 NullPointerException)
if ("admin".equals(input)) {
// 常量在前,避免 input 为 null 时报错
}
```
```
// ❌ 陷阱 2:用 == 比较包装类
Integer a = 200;
Integer b = 200;
if (a == b) { // false!超出缓存范围
// 可能不会执行
}
// ✅ 正确写法
if (a.equals(b)) {
// 正确执行
}
```
### **8.3 核心要点记忆图**
```drawio
```